package middleware

import (
	"context"
	"reflect"
	"strings"

	"google.golang.org/grpc"
)

func CloudRuInterceptor() grpc.UnaryServerInterceptor {
	return func(
		ctx context.Context,
		req any,
		_ *grpc.UnaryServerInfo,
		handler grpc.UnaryHandler,
	) (any, error) {
		value := reflect.ValueOf(req)
		handleFields(&value)
		return handler(ctx, req)
	}
}

// handleFields обрабатывает каждое поле запроса, если необходимо ограничить поля
// можно указать имена полей в fieldNames, в формате поля структуры - например "ProjectId"
func handleFields(value *reflect.Value, fieldNames ...string) {
	elem := value.Elem()
	if elem.Kind() == reflect.Struct {
		if len(fieldNames) > 0 {
			for _, name := range fieldNames {
				field := elem.FieldByName(name)
				handleField(&field)
			}
		} else {
			for i := 0; i < elem.NumField(); i++ {
				field := elem.Field(i)
				handleField(&field)
			}
		}
	}
}

func handleField(field *reflect.Value) {
	if field.IsValid() && field.CanSet() {
		switch field.Kind() {
		case reflect.String:
			trimValue := strings.Trim(field.String(), " \r\n\t")
			field.SetString(trimValue)
		case reflect.Struct, reflect.Pointer:
			// рекурсивно обрабатываем поля, которые структуры
			// Pointer - т.к. в grpc все вложенные структуры - указатели
			handleFields(field)
		default:
			return
		}
	}
}
